home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Java 1996 August
/
Java - Summer 1996.iso
/
kaffe-0.2
/
kaffe2native
/
kaffe2native.c
next >
Wrap
C/C++ Source or Header
|
1996-02-12
|
10KB
|
585 lines
/*
* kaffe2native.c
* This program reads in a kaffe.def file and converts it to the necessary
* source files for the kaffe machine.
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
*/
#include <stdio.h>
void openFiles(void);
void process(void);
void processInstruction(void);
void processRegister(void);
void processOpcodes(void);
void getLine(void);
void skipSpace(void);
void finish(void);
#define SHEADER \
"/*\n\
* instn.c\n\
* Real instruction and register information.\n\
*/\n\
\n\
#include \"instruction.h\"\n\
#include \"register.h\"\n\
#include \"gen.h\"\n\
\n\
/*\n\
* Declare the translation between Kaffe VM instructions and native instructions.\n\
*/\n\
nativeInstn instnTable[256] = {\n\
\n\
/* in, out, size, emulate, code */\n"
#define GHEADER \
"/*\n\
* gen.c\n\
* Generated instruction sequences.\n\
*/\n\
\n\
#include <assert.h>\n\
#include \"instruction.h\"\n\
#include \"soft.h\"\n\
#include \"asm.h\"\n\
\n\
void gen_UNKNOWN(instn* i)\n\
{\n\
}\n\
\n"
#define GHEADERH \
"/*\n\
* gen.h\n\
* Generated instruction sequences.\n\
*/\n\
\n\
typedef void (*genfunc)(instn*);\n\
\n\
void gen_UNKNOWN(instn*);\n\
"
#define BHEADERH \
"/*\n\
* bytecode.h\n\
* Generate bytecode defines.\n\
*/\n\
\n\
#ifndef __bytecode_h\n\
#define __bytecode_h\n\
\n\
typedef unsigned char bytecode;\n\
\n"
#define MAXREG 64
#define MAXOP 256
#define MAXBUF 200
#define SOUT "instn.c"
#define GOUT "gen.c"
#define GOUTH "gen.h"
#define BOUTH "bytecode.h"
FILE* in;
FILE* sout;
FILE* gout;
FILE* gouth;
FILE* bouth;
int line;
char* buf;
int regno;
char opcode[MAXOP][MAXBUF];
char regs[MAXREG][MAXBUF];
main(int c, char* argv[])
{
char* input = "kaffe.def";
if (c == 2) {
input = argv[1];
}
in = fopen(input, "r");
if (in == 0) {
fprintf(stderr, "Cannot find %s\n", input);
exit(1);
}
openFiles();
fputs(SHEADER, sout);
fputs(GHEADER, gout);
fputs(GHEADERH, gouth);
fputs(BHEADERH, bouth);
process();
finish();
exit(0);
}
void
openFiles(void)
{
sout = fopen(SOUT, "w");
if (sout == 0) {
fprintf(stderr, "Cannot create %s\n", SOUT);
exit(1);
}
gout = fopen(GOUT, "w");
if (gout == 0) {
fprintf(stderr, "Cannot create %s\n", GOUT);
exit(1);
}
gouth = fopen(GOUTH, "w");
if (gouth == 0) {
fprintf(stderr, "Cannot create %s\n", GOUTH);
exit(1);
}
bouth = fopen(BOUTH, "w");
if (bouth == 0) {
fprintf(stderr, "Cannot create %s\n", BOUTH);
exit(1);
}
}
void
process(void)
{
while (getLine(), buf != 0) {
if (buf[0] == '#' || isspace(buf[0])) {
continue;
}
else if (strncmp(buf, "insn", 4) == 0) {
processInstruction();
}
else if (strncmp(buf, "reg", 3) == 0) {
processRegister();
}
else {
fprintf(stderr, "Bad data at line %d\n", line);
exit(1);
}
}
}
/*
* eg. insn FADD(in=float,float; out=float; sync) = 98
*/
void
processInstruction(void)
{
char* name;
char* type;
int ins;
int outs;
int op;
int soft;
type = "i_hard";
buf += 4;
skipSpace();
name = buf;
for (; *buf != 0; buf++) {
if (*buf == '(' || isspace(*buf)) {
*buf = 0;
buf++;
goto inout;
}
}
fprintf(stderr, "Bad instruction format at line %d\n", line);
exit(1);
inout:
for(;;) {
skipSpace();
if (buf[0] == ')') {
buf++;
break;
}
if (strncmp(buf, "in=", 3) == 0) {
buf += 3;
ins = countTypes();
}
else if (strncmp(buf, "out=", 4) == 0) {
buf += 4;
outs = countTypes();
}
else if (strncmp(buf, "sync", 4) == 0) {
buf += 4;
type = "i_sync";
soft = 1;
}
else if (strncmp(buf, "soft", 4) == 0) {
buf += 4;
type = "i_soft";
soft = 1;
}
else if (strncmp(buf, "hard", 4) == 0) {
buf += 4;
type = "i_hard";
soft = 0;
}
}
skipSpace();
if (buf[0] == '=') {
buf++;
}
skipSpace();
op = atoi(buf);
if (op >= MAXOP) {
fprintf(stderr, "Opcode too big at line %d\n", line);
exit(1);
}
/* Supress ins and outs for sync and soft instructions */
if (soft == 1) {
ins = 0;
outs = 0;
}
sprintf(opcode[op], " { %d, %d, %d, %s, gen_%s },\n",
ins, outs, 0, type, name);
getLine();
if (buf[0] != '{') {
fprintf(stderr, "No code body at line %d\n", line);
exit(1);
}
fprintf(gouth, "void gen_%s(instn*);\n", name);
fprintf(gout, "void gen_%s(instn* i)\n{\n", name);
fprintf(bouth, "#define %s %d\n", name, op);
for (;;) {
getLine();
if (buf[0] == '}') {
break;
}
processOpcodes();
}
fprintf(gout, "}\n\n");
}
void
processOpcodes(void)
{
int i;
int j;
int a;
char obuf[MAXBUF];
char abuf[MAXBUF];
int r;
/* First handle literal escapes */
if (buf[0] == '+') {
buf++;
skipSpace();
fprintf(gout, "\t%s", buf);
return;
}
skipSpace();
/* Process opcode to something we can use as a function name */
j = 0;
i = 0;
a = 0;
abuf[0] = 0;
while (buf[i] != 0) {
switch (buf[i++]) {
/* Input register */
case 'I':
case 'W':
case 'B':
r = buf[i++] - '1';
sprintf(&abuf[a], "i->in[%d].reg->regno,", r);
obuf[j++] = 'R';
break;
/* Output register */
case 'O':
r = buf[i++] - '1';
sprintf(&abuf[a], "i->out[%d].reg->regno,", r);
obuf[j++] = 'R';
break;
/* Local constant */
case 'C':
/* Integer value */
case 'V':
r = buf[i++] - '1';
sprintf(&abuf[a], "i->value[%d],", r);
obuf[j++] = 'V';
break;
/* Local variable */
case 'L':
r = buf[i++] - '1';
sprintf(&abuf[a], "4*(i->value[%d]),REG_BASE,", r);
obuf[j++] = 'V';
obuf[j++] = 'o';
obuf[j++] = 'R';
obuf[j++] = 'o';
break;
/* Stack value */
case 'S':
r = buf[i++] - '1';
sprintf(&abuf[a], "4*%d,REG_STACK,", r);
obuf[j++] = 'V';
obuf[j++] = 'o';
obuf[j++] = 'R';
obuf[j++] = 'o';
break;
/* Jump address */
case 'J':
sprintf(&abuf[a], "i->value[0],");
obuf[j++] = 'J';
break;
/* Jump to absolute address */
case 'X':
sprintf(&abuf[a], "i->value[0],");
obuf[j++] = 'X';
break;
case ',':
obuf[j++] = 'x';
break;
case '(':
case ')':
obuf[j++] = 'o';
break;
case ' ':
case '\t':
obuf[j++] = '_';
break;
case '$':
case '\n':
break;
case '*':
obuf[j++] = 's';
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-':
i--;
while (isxdigit(buf[i]) ||
buf[i] == '-' || buf[i] == 'x') {
abuf[a] = buf[i];
i++;
a++;
}
sprintf(&abuf[a], ",");
obuf[j++] = 'V';
break;
/* Specific register name */
case '%':
sprintf(&abuf[a], "REG_");
a += 4;
while (isalnum(buf[i])) {
abuf[a] = buf[i];
i++;
a++;
}
sprintf(&abuf[a], ",");
obuf[j++] = 'R';
break;
/* Soft routine calls */
case '_':
if (strncmp(&buf[i], "soft", 4) != 0) {
obuf[j++] = buf[i-1];
}
else {
sprintf(&abuf[a], "(int)");
a += 5;
while (isalnum(buf[i]) ||
buf[i] == '_') {
abuf[a] = buf[i];
i++;
a++;
}
sprintf(&abuf[a], ",");
obuf[j++] = 'X';
}
break;
default:
obuf[j++] = buf[i-1];
while (isalnum(buf[i])) {
obuf[j++] = buf[i++];
}
break;
}
a = strlen(abuf);
}
obuf[j] = 0;
for (j--; obuf[j] == '_'; j--) {
obuf[j] = 0;
}
if (a > 0 && abuf[a-1] == ',') {
abuf[a-1] = 0;
}
fprintf(gout, "\tasm__%s(%s);\n", obuf, abuf);
}
/*
* eg. reg %eax int = 0
*/
void
processRegister(void)
{
char* name;
char* type;
char* nr;
buf += 3;
skipSpace();
name = buf;
for (; *buf != 0; buf++) {
if (*buf == ',' || isspace(*buf)) {
*buf = 0;
buf++;
goto wn;
}
}
fprintf(stderr, "Bad register format at line %d\n", line);
exit(1);
wn:
/* Skip type definition */
skipSpace();
type = buf;
for (; *buf != 0; buf++) {
if (*buf == ',' || isspace(*buf)) {
*buf = 0;
buf++;
goto nn;
}
}
fprintf(stderr, "Bad register format at line %d\n", line);
exit(1);
nn:
skipSpace();
buf++; /* Skip = */
skipSpace();
nr = buf;
if (regno >= MAXREG) {
fprintf(stderr, "Register number too big at line %d\n", line);
exit(1);
}
sprintf(regs[regno], " { \"%s\", %d, MAXSTACK, 0 },\n",
name, atoi(nr));
regno++;
}
void
finish(void)
{
int i;
/* Generate instruction table */
for (i = 0; i < 256; i++) {
if (opcode[i][0] != 0) {
fputs(opcode[i], sout);
}
else {
fputs(" { 0, 0, 0, i_soft, gen_UNKNOWN },\n", sout);
}
}
fputs("\n};\n", sout);
fputs("\nnativeReg registerFile[] = {\n", sout);
for (i = 0; i < regno; i++) {
fputs(regs[i], sout);
}
fputs("};\n", sout);
fprintf(bouth, "\n#endif\n");
}
int
countTypes(void)
{
int count = 0;
for (;;) {
skipSpace();
if (buf[0] == ',') {
buf++;
}
else if (buf[0] == ')') {
return (count);
}
else if (buf[0] == ';') {
buf++;
return (count);
}
skipSpace();
if (strncmp(buf, "none", 4) == 0) {
buf += 4;
count = 0;
}
else if (strncmp(buf, "any", 3) == 0) {
buf += 3;
count += 1;
}
else if (strncmp(buf, "int", 3) == 0) {
buf += 3;
count += 1;
}
else if (strncmp(buf, "long", 4) == 0) {
buf += 4;
count += 2;
}
else if (strncmp(buf, "float", 5) == 0) {
buf += 5;
count += 1;
}
else if (strncmp(buf, "double", 6) == 0) {
buf += 6;
count += 2;
}
else if (strncmp(buf, "objref", 6) == 0) {
buf += 6;
count += 1;
}
}
}
void
getLine(void)
{
static char lbuf[MAXBUF];
line++;
buf = fgets(lbuf, sizeof(lbuf), in);
}
void
skipSpace(void)
{
while (isspace(*buf)) {
buf++;
}
}